package cn.itcast.nems.oldems.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.oldems.dao.entiry.Student;
import cn.itcast.nems.oldems.dao.entiry.StudentContactInfo;
import cn.itcast.nems.oldems.dao.mapper.StudentContactInfoMapper;
import cn.itcast.nems.oldems.dao.mapper.StudentMapper;
import cn.itcast.nems.oldems.dto.StudentContactEditDto;
import cn.itcast.nems.oldems.dto.StudentContactListDto;
import cn.itcast.nems.oldems.service.StudentContactService;
import cn.itcast.nems.student.enumeration.StudentErrorBodyEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Service
@RequiredArgsConstructor
public class StudentContactServiceImpl implements StudentContactService {

    private final StudentContactInfoMapper studentContactInfoMapper;
    private final StudentMapper studentMapper;

    @Override
    public List<StudentContactListDto> listStudentContactInfoByStudentId(Integer studentId) {
        var list = new ArrayList<StudentContactListDto>();
        Student student = studentMapper.selectById(studentId);
        var mainP = mainPhone(student);
        if (mainP != null) {
            list.add(mainP);
        }
        var mainV = mainWeixin(student);
        if (mainV != null) {
            list.add(mainV);
        }
        var mainE = mainEmail(student);
        if (mainE != null) {
            list.add(mainE);
        }
        list.addAll(studentContactInfoMapper.selectList(
                new QueryWrapper<>(new StudentContactInfo())
                        .lambda()
                        .eq(StudentContactInfo::getStudentId, studentId)
                        .orderByDesc(StudentContactInfo::getCreatedate)
        ).stream().map(this::mapToVo).toList());
        return list;
    }

    /**
     * 获取主要手机号，若不存在则不显示，固返回null
     */
    private StudentContactListDto mainPhone(Student student) {
        if (!StringUtils.hasText(student.getPhone())) {
            return null;
        }
        StudentContactListDto vo = new StudentContactListDto();
        vo.setId(0);
        vo.setContactInfo(DesensitizedUtil.mobilePhone(student.getPhone()));
        vo.setContactType("PHONE");
        vo.setMain(Boolean.TRUE);
        return vo;
    }

    /**
     * 获取主要手机号，若不存在则不显示，固返回null
     */
    private StudentContactListDto mainWeixin(Student student) {
        if (!StringUtils.hasText(student.getQqnumber())) {
            return null;
        }
        StudentContactListDto vo = new StudentContactListDto();
        vo.setId(-1);
        vo.setContactInfo(student.getQqnumber());
        vo.setContactType("WEIXIN");
        vo.setMain(Boolean.TRUE);
        vo.setContactInfo(wxD(vo.getContactInfo()));
        return vo;
    }

    private StudentContactListDto mainEmail(Student student) {
        if (!StringUtils.hasText(student.getEmail())) {
            return null;
        }
        StudentContactListDto vo = new StudentContactListDto();
        vo.setId(-2);
        vo.setContactInfo(student.getEmail());
        vo.setContactType("EMAIL");
        vo.setMain(Boolean.TRUE);
        return vo;
    }

    /**
     * 将实体转换为VO
     *
     * @param en
     * @return
     */
    private StudentContactListDto mapToVo(StudentContactInfo en) {
        if (en == null) {
            return null;
        }
        StudentContactListDto vo = new StudentContactListDto();
        vo.setContactInfo(en.getContactInfo());
        vo.setContactType(en.getContactType());
        vo.setId(en.getId());
        vo.setMain(Boolean.FALSE);
        if ("PHONE".equals(en.getContactType())) {
            if (StringUtils.hasText(vo.getContactInfo())) {
                vo.setContactInfo(DesensitizedUtil.mobilePhone(vo.getContactInfo()));
            }
        }
        if ("WEIXIN".equals(en.getContactType())) {
            vo.setContactInfo(wxD(vo.getContactInfo()));
        }
        return vo;
    }

    private String wxD(String wx) {
        if (wx.length() <= 2) {
            return wx;
        }
        return wx.charAt(0) + "***" + wx.substring(wx.length() - 1);
    }

    private void checkContactInfo(StudentContactEditDto bo) {
        if (!StringUtils.hasText(bo.getContactInfo())) {
            BizExceptionProducer.throwProduce(StudentErrorBodyEnum.CONTACT_INFO_NOT_NULL);
        }
        if (bo.getContactType().equals("PHONE")) {
            Assert.isTrue(Pattern.matches("^1[3456789]\\d{9}$", bo.getContactInfo()), BizExceptionProducer.produce(StudentErrorBodyEnum.PHONE_FORMAT_ERROR));
        } else if (bo.getContactType().equals("EMAIL")) {
            Assert.isTrue(Pattern.matches("^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$", bo.getContactInfo()), BizExceptionProducer.produce(StudentErrorBodyEnum.EMAIL_FORMAT_ERROR));
        }
    }

    /**
     * 新增学生联系方式
     *
     * @param bo
     * @return
     */
    @Override
    @Transactional
    public Boolean addStudentContactInfo(StudentContactEditDto bo) {
        checkContactInfo(bo);
        var now = LocalDateTime.now();
        var cUser = AccountHolder.getAccount().get();
        // 若为MAIN，则会出现两种情况
        // 1. 存在主要联系方式，更新主表，并将主表的联系方式新增一条
        // 2. 不存在主要联系方式，直接更新主表
        if (bo.getMain() != null && bo.getMain()) {
            // 替换学生，上的PHONE，并且新增一条
            if (!bo.getContactType().equals("PHONE")) {
                BizExceptionProducer.throwProduce(StudentErrorBodyEnum.MAIN_MUST_BE_PHONE);
            }
            var student = studentMapper.selectById(bo.getStudentId());
            studentMapper.update(
                    null,
                    new UpdateWrapper<Student>()
                            .lambda()
                            .eq(Student::getId, student.getId())
                            .set(Student::getPhone, bo.getContactInfo())
            );
            bo.setContactInfo(student.getPhone());
            // 主表之前不存在联系方式，忽略新增
            if (!StringUtils.hasText(bo.getContactInfo())) {
                return Boolean.TRUE;
            }
        }
        // 直接新增一条
        StudentContactInfo contactInfo = new StudentContactInfo();
        contactInfo.setContactInfo(bo.getContactInfo());
        contactInfo.setContactType(bo.getContactType());
        contactInfo.setCreatedate(now);
        contactInfo.setStudentId(bo.getStudentId());
        contactInfo.setOperatorUsername(cUser);
        contactInfo.setOperatorUealname(cUser);
        studentContactInfoMapper.insert(contactInfo);
        return Boolean.TRUE;
    }

    /**
     * 编辑学生联系方式
     *
     * @param bo
     * @return
     */

    @Override
    @Transactional
    public Boolean editStudentContactInfo(StudentContactEditDto bo) {
        checkContactInfo(bo);
        var cUser = AccountHolder.getAccount().get();
        // 编辑
        // 1. 可能将任意联系方式更新为主要联系方式
        // 2. 可能只更新主要联系方式
        // 3. 可能只更新非主要联系方式
        if (bo.getMain() != null && bo.getMain()) {
            // 更新主要，那么只能为手机号
            if (!bo.getContactType().equals("PHONE")) {
                BizExceptionProducer.throwProduce(StudentErrorBodyEnum.MAIN_MUST_BE_PHONE);
            }
            // 更新主要，替换学生，上的PHONE
            var student = studentMapper.selectById(bo.getStudentId());
            studentMapper.update(
                    null,
                    new UpdateWrapper<Student>()
                            .lambda()
                            .eq(Student::getId, student.getId())
                            .set(Student::getPhone, bo.getContactInfo())
            );
            // 如果更新附表信息到主表，两者需要替换
            bo.setContactInfo(student.getPhone());
            // ID为0，说明意图只为了更新主表，可以直接忽略接下来的操作
            if (bo.getContactId() == null || bo.getContactId() == 0) return Boolean.TRUE;
            // 如果不是编辑主角表，需要新增一条
        }
        if (bo.getContactId() == -1) {
            // 更新主表的微信
            studentMapper.update(
                    null,
                    new UpdateWrapper<Student>()
                            .lambda()
                            .eq(Student::getId, bo.getStudentId())
                            .set(Student::getQqnumber, bo.getContactInfo())
            );
            return Boolean.TRUE;
        }
        if (bo.getContactId() == -2) {
            // 更新主表的微信
            studentMapper.update(
                    null,
                    new UpdateWrapper<Student>()
                            .lambda()
                            .eq(Student::getId, bo.getStudentId())
                            .set(Student::getEmail, bo.getContactInfo())
            );
            return Boolean.TRUE;
        }
        // 修改附表信息
        studentContactInfoMapper.update(
                null,
                new UpdateWrapper<StudentContactInfo>()
                        .lambda()
                        .eq(StudentContactInfo::getId, bo.getContactId())
                        .set(StudentContactInfo::getContactType, bo.getContactType())
                        .set(StudentContactInfo::getContactInfo, bo.getContactInfo())
        );
        return Boolean.TRUE;
    }

    /**
     * 删除学生联系方式
     *
     * @param bo
     * @return
     */

    @Override
    @Transactional
    public Boolean deleteStudentContactInfo(StudentContactEditDto bo) {
        var cUser = AccountHolder.getAccount().get();
        // 直接删除联系方式即可，只要不是主要联系方式
        if (bo.getContactId() == null || bo.getContactId() == 0) {
            BizExceptionProducer.throwProduce(StudentErrorBodyEnum.MAIN_MUST_BE_PHONE);
        }
        if (bo.getContactId() == -1) {
            // 更新主表的微信
            studentMapper.update(
                    null,
                    new UpdateWrapper<Student>()
                            .lambda()
                            .eq(Student::getId, bo.getStudentId())
                            .set(Student::getQqnumber, "")
            );
            return Boolean.TRUE;
        }
        if (bo.getContactId() == -2) {
            // 更新主表的微信
            studentMapper.update(
                    null,
                    new UpdateWrapper<Student>()
                            .lambda()
                            .eq(Student::getId, bo.getStudentId())
                            .set(Student::getEmail, "")
            );
            return Boolean.TRUE;
        }
        studentContactInfoMapper.deleteById(bo.getContactId());
        return Boolean.TRUE;
    }

    @Override
    public Map<Integer, String> mapContact(List<Integer> studentIdList, String email) {
        var map = new HashMap<Integer, String>();
        if (!CollectionUtils.isEmpty(studentIdList)) {
            for (StudentContactInfo studentContactInfo : studentContactInfoMapper.selectList(
                    new QueryWrapper<StudentContactInfo>()
                            .lambda()
                            .in(StudentContactInfo::getStudentId, studentIdList)
                            .eq(StudentContactInfo::getContactType, email)
            )) {
                map.put(studentContactInfo.getStudentId(), studentContactInfo.getContactInfo());
            }
        }
        return map;
    }
}
